package org.jeecg.modules.commu;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.A;
import org.codehaus.jettison.json.JSONString;
import org.jeecg.boot.starter.rabbitmq.client.RabbitMqClient;
import org.jeecg.boot.starter.rabbitmq.core.BaseRabbiMqHandler;
import org.jeecg.boot.starter.rabbitmq.listenter.MqListener;
import org.jeecg.common.annotation.RabbitComponent;
import org.jeecg.common.base.BaseMap;
import org.jeecg.modules.device.DeviceContainer;
import org.jeecg.modules.device.TigDeviceShadow;
import org.jeecg.modules.driver.DriverCommandList;
import org.jeecg.modules.device.Device;
import org.jeecg.modules.entity.TigDevice;
import org.jeecg.modules.entity.TigDeviceTcpLog;
import org.jeecg.modules.message.DeviceListWebSocket;
import org.jeecg.modules.message.DeviceWebSocket;
import org.jeecg.modules.entity.TigerDeviceLog;
import org.jeecg.modules.service.DeviceService;
import org.jeecg.modules.service.ITigDeviceService;
import org.jeecg.modules.service.ITigDeviceTcpLogService;
import org.jeecg.modules.service.ITigerDeviceLogService;
import org.jeecg.modules.util.ConvertUtil;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Header;

import java.time.LocalDate;
import java.util.Date;

@Slf4j
@RabbitComponent(value = "deviceDataListner1")
public class RabbitMqListner1 extends BaseRabbiMqHandler<BaseMap> {

    @Autowired
    DeviceContainer deviceContainer;

    @Autowired
    DeviceService deviceService;

    @Autowired
    DeviceWebSocket deviceWebSocket;

    @Autowired
    DeviceListWebSocket deviceListWebSocket;

    @Autowired
    ITigerDeviceLogService iTigerDeviceLogService;

    @Autowired
    ITigDeviceTcpLogService iTigDeviceTcpLogService;

    @Autowired
    private RabbitMqClient rabbitMqClient;

    @Autowired
    private ITigDeviceService iTigDeviceService;


    @RabbitListener(queues = "devicedata")
    public void onMessage(BaseMap baseMap, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
        super.onMessage(baseMap, deliveryTag, channel, new MqListener<BaseMap>() {
            @Override
            public void handler(BaseMap map, Channel channel) {
                String deviceId = map.get("deviceId");
                String dataStr = map.get("data");
                String cmd = map.get("cmd");

                if (deviceId == null) return;

                //判断接收到处理消息的时候设备是否已经从数据库删除了
                if (iTigDeviceService.getById(deviceId) == null){
                    log.error("deviceData error Msg:device id = " + deviceId + "has been delete,you can't get it again");
                    return;
                }

                TigDeviceShadow sd = deviceContainer.getShadowDevice(deviceId);

                try {
                    if (sd == null) return;//没有这个设备连接上
                    Device d = sd.getDevice();
                    if (deviceId != null) {
                        {
                            String[] data = dataStr.toString().split("##");
                            cmd = data[0];
//                            log.info("command:" + cmd);
                            saveDeviceDataLog(sd, cmd, dataStr);
                            //处理设备离线请求
                            if (data[0].equals(DriverCommandList.D_LOCAL_DISCONNECT)) {
                                generateDeviceStateChangeLog(d, "离线");
                                d = resolveDisconnect(deviceId, sd, data);
                            } else if (data[0].equals(DriverCommandList.D_LOCAL_CONNECTED)) {
                                sd.getDevice().getDeviceDriver().resolveCommand(data[0], data[1]);
                                d = sd.getDevice();
                                generateDeviceStateChangeLog(d, "上线");
                            } else {
                                //处理普通请求
                                sd.getDevice().getDeviceDriver().resolveCommand(data[0], data[1]);
                                d = sd.getDevice();
                            }
                        }
                        if (d != null) {
                            //检查状态变更是否需要保存报警日志
                            checkStateChange(cmd, d);
                            //保存状态
                            deviceService.saveDevice(d);
                            //发送结果
                            TigDevice tigd = sd.getTigDeviceEntity();
                            String strDeviceJson = JSON.toJSONString(tigd);
                            JSONObject deviceJson = JSONObject.parseObject(strDeviceJson);
                            JSONObject shadowJson = JSONObject.parseObject(d.getShadow().toString());
                            deviceJson.put("shadow", shadowJson);
                            deviceWebSocket.pushMessage(deviceId, deviceJson.toString());
                            deviceListWebSocket.pushMessage(deviceId, deviceJson.toString());

                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    private void saveDeviceDataLog(TigDeviceShadow sd, String command, String content) throws Exception {
//        暂时屏蔽
//        if (sd != null) {
//            TigDeviceTcpLog log = new TigDeviceTcpLog();
//            log.setDeviceName(sd.getDevice().getShadow().getJSONObject("baseinfo").getString("name"));
//            log.setDeviceId(sd.getDevice().getId());
//            log.setContent(content);
//            log.setCommand(command);
//            log.setDirection("上报");
//            iTigDeviceTcpLogService.save(log);
//        }
    }

    private boolean checkStateChange(String d_cmd, Device d) throws Exception {
        //Send to wanning queue
        if (d_cmd.equals(DriverCommandList.D_deviceWanringChannel)
                || d_cmd.equals(DriverCommandList.D_deviceWarningDevice)) {
            BaseMap map = new BaseMap();
            map.put("deviceId", d.getId());
            map.put("data", d.getShadow().toString());
            map.put("cmd", d_cmd);
            rabbitMqClient.sendMessage("warningData", map);

        }

        return true;
    }

    private void generateDeviceWarningLog(Device d, String warningMsg) throws Exception {
        TigerDeviceLog log = new TigerDeviceLog();
        log.setName(d.getShadow().getJSONObject("baseinfo").getString("name"));
        log.setDeviceId(d.getId());
        log.setLogTime(new Date(Long.parseLong(d.getShadow().getString("cmdTime"))));
        log.setContent(warningMsg);
        log.setLogType("1");
        log.setSysOrgCode(deviceService.getTigDevice(d.getId()).getSysOrgCode());
        iTigerDeviceLogService.save(log);
    }

    private void generateDeviceStateChangeLog(Device d, String state) throws Exception {
        TigerDeviceLog log = new TigerDeviceLog();
        log.setName(d.getShadow().getJSONObject("baseinfo").getString("name"));
        log.setDeviceId(d.getId());
        log.setLogTime(new Date(Long.parseLong(d.getShadow().getString("cmdTime"))));
        log.setContent(state);
        log.setLogType("8");//数据记录
        log.setHandleStatus("0");//未处理
        log.setLogCategory("3");//普通类型
        log.setSysOrgCode(deviceService.getTigDevice(d.getId()).getSysOrgCode());
        iTigerDeviceLogService.save(log);
        String name = "设备【" + d.getShadow().getJSONObject("baseinfo").getString("name") + "】上下线告警消息";
        String anMsg = "设备【" + d.getShadow().getJSONObject("baseinfo").getString("name") + "】" + state;
        deviceService.sendAnnouncementToDepartment(d.getId(), name, anMsg);
    }

    private Device resolveDisconnect(String deviceId, TigDeviceShadow sd, String[] data) {
        if (sd != null) {
            //正在链接的设备断线
            sd.disConnect();
            deviceService.disconnect(deviceId, false);
            return sd.getDevice();
        } else {
            //没有在线的设备状态变更
            Device s = deviceService.getDevice(deviceId);
            return s;
        }
    }

}
